<?php

namespace app\common\command\task;

use app\common\command\Task;
use app\common\model\Course;
use app\common\model\CoursePaper;
use app\common\model\CourseQuestion;
use PhpOffice\PhpWord\PhpWord;
use PhpOffice\PhpWord\IOFactory;

/**
 * 生成试卷电子档
 */
class GeneratePaperDocument extends Task
{
    /**
     * 执行任务
     * @return void
     */
    public function invoke()
    {
        // 控制开关：是否生成答案和解析
        $showAnswerAndExplanation = false; // 设置为false则不生成答案和解析
        
        // 查询多个试卷
        $paperModel = new CoursePaper();
        $where = [
            ['course_id', '=', 603],
            ['tag_id', '=', 40],
            ['id', '=', 64380],
        ];
        $papers = $paperModel->where($where)->select();
        if (!$papers || $papers->isEmpty()) {
            return;
        }

        // 处理多个试卷
        foreach ($papers as $paper) {
            // 查询课程信息
            $courseModel = new Course();
            $course = $courseModel->find($paper->course_id);
            if (!$course) {
                continue; // 跳过没有对应课程的试卷
            }

            // 生成试卷名称
            $paperName = $course->name;
            if($course['code']){
                $paperName .= '【' . $course['code'].'】';
            }
            $paperName .= $paper['name'];

            // 查询当前试卷的题目
            $questionModel = new CourseQuestion();
            $questions = $questionModel->where('extend_id', $paper->id)->select();
            if ($questions->isEmpty()) {
                continue; // 跳过没有题目的试卷
            }

            // 为每个试卷创建独立的Word文档
            $phpWord = new PhpWord();

            // 设置文档默认字体和样式
            $phpWord->setDefaultFontName('宋体'); // 使用宋体作为默认字体
            $phpWord->setDefaultFontSize(12);

            // 添加一个章节并设置页眉
            $section = $phpWord->addSection();
            $header = $section->addHeader();
            $header->addText('翰林刷题小程序', ['name' => '宋体', 'size' => 12, 'bold' => true], ['alignment' => 'center']);

            // 添加试卷标题（清洗后）
            $section->addText($this->cleanTextForXml($paperName), ['bold' => true, 'size' => 18, 'name' => '黑体'], ['alignment' => 'center']);
            $section->addTextBreak(2); // 标题后增加更多间距

            // 添加题目
            $totalQuestions = count($questions);
            echo "正在处理试卷 {$paperName}，共 {$totalQuestions} 道题" . PHP_EOL;
            
            foreach ($questions as $index => $question) {
                $questionNumber = $index + 1;
                echo "正在处理第 {$questionNumber} 道题，题目ID: {$question->id}" . PHP_EOL;
                
                $questionTitle = $questionNumber . '、' . $question->question_name;

                // 清理HTML标签并处理特殊字符
                $questionTitle = strip_tags($questionTitle);
                $questionTitle = htmlspecialchars_decode($questionTitle, ENT_QUOTES);
                // 进一步清理特殊字符，确保符合XML标准
                $questionTitle = $this->cleanTextForXml($questionTitle);

                $section->addText($questionTitle, ['size' => 14, 'name' => '宋体', 'bold' => true]);
                
                // 调试：每10道题输出一次文档内容统计
                if ($questionNumber % 10 == 0) {
                    echo "  📊 已添加 {$questionNumber} 道题，当前段落数: " . count($section->getElements()) . PHP_EOL;
                }

                // 解析question_data字段
                if (!empty($question->question_data)) {
                    $questionData = json_decode($question->question_data, true);
                    if (json_last_error() !== JSON_ERROR_NONE) {
                        // JSON解析失败，记录错误但继续处理
                        echo "警告：题目ID {$question->id} 的question_data解析失败，跳过选项处理" . PHP_EOL;
                        $questionData = null;
                    }
                    if ($questionData) {
                        // 处理选项（单选、多选、判断题统一处理）
                        if (in_array($question->question_type, [1, 2, 3])) { // 单选、多选、判断题
                            if (isset($questionData['answerOption']) && is_array($questionData['answerOption']) && !empty($questionData['answerOption'])) {
                                $options = $questionData['answerOption'];
                                $section->addTextBreak(1); // 选项列表前增加间距
                                foreach ($options as $key => $option) {
                                    // 跳过空选项，但继续处理其他选项
                                    if (empty($option) || trim($option) === '') {
                                        continue;
                                    }
                                    // 清理HTML标签并处理特殊字符
                                    $option = strip_tags($option);
                                    $option = htmlspecialchars_decode($option, ENT_QUOTES);
                                    // 进一步清理特殊字符，确保符合XML标准
                                    $option = $this->cleanTextForXml($option);
                                    $section->addText('    ' . $key . '. ' . $option, ['size' => 13, 'name' => '宋体']);
                                    $section->addTextBreak(1); // 每个选项后增加1行间距
                                }
                                $section->addTextBreak(1);
                            }
                        }

                        // 添加正确答案（清洗后）
                        if ($showAnswerAndExplanation && isset($questionData['correctOption'])) {
                            $correctText = $this->cleanTextForXml(htmlspecialchars_decode(strip_tags((string)$questionData['correctOption']), ENT_QUOTES));
                            $section->addText('正确答案：' . $correctText, ['bold' => true, 'size' => 14, 'color' => 'FF0000', 'name' => '宋体']);
                            $section->addTextBreak(1);
                        }

                        // 添加解析（清洗后）
                        if ($showAnswerAndExplanation) {
                            $explainText = '';
                            if (isset($questionData['aiExplanation']) && !empty($questionData['aiExplanation'])) {
                                $explainText = $questionData['aiExplanation'];
                            } elseif (isset($questionData['explanation']) && !empty($questionData['explanation'])) {
                                $explainText = $questionData['explanation'];
                            }
                            if ($explainText !== '') {
                                $explainText = $this->cleanTextForXml(htmlspecialchars_decode(strip_tags((string)$explainText), ENT_QUOTES));
                                $section->addText('解析：' . $explainText, ['size' => 12, 'name' => '宋体', 'italic' => false]);
                            }
                        }

                        // 每道题之间添加明显的分隔线
                        $section->addTextBreak(1);
                        $section->addText('─────────────────────────────', ['size' => 10, 'name' => '宋体', 'color' => 'CCCCCC']);
                        $section->addTextBreak(1);
                    }
                }

                $section->addTextBreak(1);
            }

            // 添加参考答案部分（即使$showAnswerAndExplanation为false也生成）
            $section = $phpWord->addSection();
            $section->addText('参考答案', ['bold' => true, 'size' => 16, 'name' => '黑体'], ['alignment' => 'center']);
            $section->addTextBreak(2);
            
            foreach ($questions as $index => $question) {
                $questionNumber = $index + 1;
                if (!empty($question->question_data)) {
                    $questionData = json_decode($question->question_data, true);
                    if (isset($questionData['correctOption'])) {
                        $correctText = $this->cleanTextForXml(htmlspecialchars_decode(strip_tags((string)$questionData['correctOption']), ENT_QUOTES));
                        $section->addText($questionNumber . '. ' . $correctText, ['size' => 14, 'name' => '宋体']);
                        $section->addTextBreak(1);
                    }
                }
            }
            
            // 保存Word文档
            // 处理文件名中的特殊字符，确保文件系统兼容性
            $safePaperName = preg_replace('/[^a-zA-Z0-9\-_\x{4e00}-\x{9fa5}]/u', '_', $paperName);
         // 保存文档
        $filename = $safePaperName . '_' . date('YmdHis') . '.docx';
        $filepath = runtime_path() . $filename;
        
        // 添加调试信息：统计实际添加的内容
        echo "文档统计信息：\n";
        echo "- 总段落数: " . count($section->getElements()) . "\n";
        echo "- 文档保存路径: " . $filepath . "\n";
        
        try {
            echo "开始创建文档写入器...\n";
            $objWriter = IOFactory::createWriter($phpWord, 'Word2007');
            echo "文档写入器创建成功，开始保存文档...\n";
            $objWriter->save($filepath);
            echo "✅ 文档成功保存，文件大小: " . filesize($filepath) . " 字节\n";
            
            // 验证文件是否真正保存成功
            if (!file_exists($filepath)) {
                echo "❌ 警告：文档保存后文件不存在！\n";
            } elseif (filesize($filepath) == 0) {
                echo "❌ 警告：文档保存后文件大小为0！\n";
            } else {
                echo "✅ 文档验证通过\n";
            }
        } catch (\Exception $e) {
            echo "❌ 保存文档时出错: " . $e->getMessage() . "\n";
            echo "错误文件: " . $e->getFile() . "\n";
            echo "错误行号: " . $e->getLine() . "\n";
            throw $e;
        } catch (\Error $e) {
            echo "❌ 保存文档时发生致命错误: " . $e->getMessage() . "\n";
            echo "错误文件: " . $e->getFile() . "\n";
            echo "错误行号: " . $e->getLine() . "\n";
            throw $e;
        }

            echo '试卷电子档生成完成，文件路径：' . $filepath . PHP_EOL;
        }
    }

    private function executeItem($index, $question) {}
    
    /**
     * 清理文本中的特殊字符，确保符合XML标准
     * 
     * @param string $text 待清理的文本
     * @return string 清理后的文本
     */
    private function cleanTextForXml($text) {
        // 移除或替换可能导致XML解析错误的特殊字符
        $text = preg_replace('/[\x00-\x08\x0B\x0C\x0E-\x1F\x7F]/', '', $text);
        
        // 替换特殊HTML实体
        $text = str_replace(['&nbsp;', '&mdash;', '&ndash;', '&hellip;'], [' ', '—', '–', '…'], $text);
        
        // 确保文本编码为UTF-8
        if (mb_check_encoding($text, 'UTF-8')) {
            // 如果已经是UTF-8编码，则进行清理
            $text = mb_convert_encoding($text, 'UTF-8', 'UTF-8');
        } else {
            // 尝试转换为UTF-8
            $text = mb_convert_encoding($text, 'UTF-8');
        }
        
        // 移除控制字符，但保留换行符和制表符
        $text = preg_replace('/[\x00-\x09\x0B\x0C\x0E-\x1F\x7F]/u', '', $text);

        // 移除非BMP字符(例如 emoji 等)，避免 Word 修复文档导致内容丢失
        $text = preg_replace('/[\x{10000}-\x{10FFFF}]/u', '', $text);
        
        return $text;
    }
}
